#ifndef MYBIGNUM_H
#define MYBIGNUM_H
#include <openssl/bn.h>
#include <string>
#include <iostream>

class MyBIGNUM
{
public:
    MyBIGNUM();
    MyBIGNUM(BIGNUM* bn);
    ~MyBIGNUM();
    MyBIGNUM(const MyBIGNUM& other);
    MyBIGNUM(const MyBIGNUM&& other);
    BIGNUM* getNum() const{return m_num;}
    MyBIGNUM& operator=(const MyBIGNUM& other);
    MyBIGNUM& operator=(const MyBIGNUM&& other);
    bool setNumFromWord(BN_ULONG);
    bool setNumFromDec(std::string);
    bool setNumFromHex(std::string);
    bool setNumFromUChar(const unsigned char* s,int len);
    bool setBitsToOne(int bits);
    void setNumToZero();
    bool isNull(){return m_num==nullptr;}
    //生成大素数
    static MyBIGNUM getANewPramix(int bits,int safe);
    //生成指定位数的随机数
    static MyBIGNUM rand(int bits);
    //生成指定范围的随机正数
    static MyBIGNUM rand(const MyBIGNUM& limit);
    //加法
    MyBIGNUM operator+(const MyBIGNUM& a);
    MyBIGNUM operator+(const BN_ULONG& a);
    MyBIGNUM operator+(BN_ULONG&& a);
    friend MyBIGNUM operator+(BN_ULONG a,const MyBIGNUM& b);
    //模加
    MyBIGNUM addMod(const MyBIGNUM& a,const MyBIGNUM& mod);
    MyBIGNUM addMod(BN_ULONG a,const MyBIGNUM& mod);
    MyBIGNUM addMod(BN_ULONG a,const MyBIGNUM&& mod);
    MyBIGNUM addMod(const MyBIGNUM& a,BN_ULONG mod);
    //减法
    MyBIGNUM operator-(const MyBIGNUM& a);
    MyBIGNUM operator-(const BN_ULONG& a);
    MyBIGNUM operator-(BN_ULONG&& a);
    friend MyBIGNUM operator-(BN_ULONG a,const MyBIGNUM& b);
    MyBIGNUM subMod(const MyBIGNUM& a,const MyBIGNUM& mod);
    MyBIGNUM subMod(BN_ULONG a,const MyBIGNUM& mod);
    MyBIGNUM subMod(const MyBIGNUM& a,BN_ULONG mod);
    //成法
    MyBIGNUM operator*(const MyBIGNUM& a);
    MyBIGNUM operator*(const BN_ULONG& a);
    MyBIGNUM operator*(BN_ULONG&& a);
    friend MyBIGNUM operator*(BN_ULONG a,const MyBIGNUM& b);
    MyBIGNUM mulMod(const MyBIGNUM& a,const MyBIGNUM& mod);
    MyBIGNUM mulMod(BN_ULONG a, const MyBIGNUM &mod);
    MyBIGNUM mulMod(const MyBIGNUM &a, BN_ULONG mod);
    //除法
    MyBIGNUM operator/(const MyBIGNUM& a);
    MyBIGNUM operator/(const BN_ULONG& a);
    MyBIGNUM operator/(BN_ULONG&& a);
    friend MyBIGNUM operator/(BN_ULONG a,const MyBIGNUM& b);
    MyBIGNUM inverseMod(const MyBIGNUM &mod);
    //取余数
    MyBIGNUM operator%(const MyBIGNUM& mod);
    //异或运算
    MyBIGNUM operator^(const MyBIGNUM& a);
    //幂运算
    MyBIGNUM exp(const MyBIGNUM& a);
    MyBIGNUM exp(BN_ULONG a);
    //比较函数
    int cmp(const MyBIGNUM& a);
    bool operator==(const MyBIGNUM& a);
    bool operator!=(const MyBIGNUM& a);
    bool operator<=(const MyBIGNUM& a);
    bool operator>=(const MyBIGNUM& a);
    bool operator<(const MyBIGNUM& a);
    bool operator>(const MyBIGNUM& a);
    //打印
    void print();
    friend class MyECPoint;
    friend class MainWindow;
    friend std::ostream& operator<<(std::ostream& os, const MyBIGNUM& dt);
    //返回字符串
    std::string toString();
    //如果
    BN_ULONG toBN_ULONG();
private:
    BIGNUM* m_num=nullptr;
};

#endif // MYBIGNUM_H
